<?php

namespace App\Console\Commands;

use Config;
use Illuminate\Console\Command;
use Illuminate\Filesystem\Filesystem;
use Illuminate\Support\Composer;

class Workers extends Command
{
    /**
     * The name and signature of the console command.
     *
     * @var string
     */
    protected $signature = 'make:workers {worker}';

    /**
     * The console command description.
     *
     * @var string
     */
    protected $description = 'make a workerman file';

    /**
     * Create a new command instance.
     *
     * @param Filesystem $filesystem
     * @param Composer $composer
     * @return void
     */
    public function __construct(Filesystem $filesystem, Composer $composer)
    {
        parent::__construct();
        $this->files       = $filesystem;
        $this->composer    = $composer;
    }

    /**
     * Execute the console command.
     *
     * @return mixed
     */
    public function handle()
    {
        //获取worker参数值
        $argument = $this->argument('worker');
        //自动生成worker文件
        $this->writeworker($argument);
        //重新生成autoload.php文件
        $this->composer->dumpAutoloads();
    }

    private function writeworker($worker)
    {
        if($this->createworker($worker)){
            //若生成成功,则输出信息
            $this->info('Success to make a '.ucfirst($worker));
        }
    }

    private function createworker($worker)
    {
        // getter/setter 赋予成员变量值
        $this->setWorker($worker);
        // 创建文件存放路径, workerInterface放在app/Worker,worker个人一般放在app/Workers/Eloquent里
        $this->createDirectory();
        // 生成两个文件
        return $this->createClass();
    }

    private function createDirectory()
    {
        $directory = $this->getDirectory();
        // echo $directory;
        //检查路径是否存在,不存在创建一个,并赋予775权限
        if(! $this->files->isDirectory($directory)){
            return $this->files->makeDirectory($directory, 0755, true);
        }
    }

    private function getDirectory()
    {
        // echo Config::get('worker.directory_path');
        return Config::get('worker.directory_path');
    }

    private function createClass()
    {
        //渲染模板文件,替换模板文件中变量值
        $templates = $this->templateStub();
        $class     = null;
        foreach ($templates as $key => $template) {
            //根据不同路径,渲染对应的模板文件
            $class = $this->files->put($this->getPath($key), $template);
        }
        return $class;
    }

    private function getPath($class)
    {
        $path = null;

        $path = $this->getDirectory().'/'.$this->getworkerName().'.php';
        return $path;
    }

    private function getWorkerName()
    {
        // 根据输入的worker变量参数,是否需要加上'Worker'
        $workerName = $this->getworker();
        if($this->addName($workerName)){
            $workerName .= 'Worker'; 
        }
        return $workerName;
    }

    private function addName($workerName){
        if (explode('Worker', $workerName)[0] != $workerName) {
            return 0;
        }else if (explode('worker', $workerName)[0] != $workerName) {
            return 0;
        }else{
           return 1; 
        }
    }

    private function getInterfaceName()
    {
        return $this->getworkerName().'Interface';
    }

    /**
     * @return mixed
     */
    public function getWorker()
    {
        return $this->worker;
    }

    /**
     * @param mixed $worker
     */
    public function setWorker($worker)
    {
        $this->worker = $worker;
    }

    private function templateStub()
    {
        // 获取两个模板文件
        $stubs        = $this->getStub();
        // 获取需要替换的模板文件中变量
        $templateData = $this->getTemplateData();
        $renderStubs  = [];
        foreach ($stubs as $key => $stub) {
            // 进行模板渲染
            $renderStubs[$key] = $this->getRenderStub($templateData, $stub);
        }

        return $renderStubs;
    }

    private function getStub()
    {
        $stubs = [
            'worker'  => $this->files->get(resource_path('stubs').DIRECTORY_SEPARATOR.'workers.stub'),
        ];

        return $stubs;
    }

    private function getTemplateData()
    {
        // $workerNamespace       = $this->getNameSpace();
        $className             = $this->getWorkerName();
        $workerFactory         = $_SERVER["DOCUMENT_ROOT"].'\\Workerman\\Worker';
        $require               = $_SERVER["DOCUMENT_ROOT"].'vendor/Workerman/Autoloader.php';

        $templateVar = [
            // 'worker_namespace'          => $workerNamespace,
            'class_name'                => $className,
            'workerFactory'             => $workerFactory, 
            'require'                   => $require,            
        ];

        return $templateVar;
    }

    private function getNameSpace(){
        $dir = explode('/', Config::get('worker.directory_path'));
        $trueDir = '';
        foreach ($dir as $key => $value) {
            if ($key == 0) {
                $trueDir .= $value;
            }else{
                $trueDir .= '\\'. $value;
            }
            
        }
        return $trueDir;
    }

    private function getRenderStub($templateData, $stub)
    {
        foreach ($templateData as $search => $replace) {
            $stub = str_replace('$'.$search, $replace, $stub);
        }

        return $stub;
    }
}
